package com.starryx.sim.mvc.controller;


import com.starryx.sim.mvc.annotation.RequestParam;
import com.starryx.sim.mvc.reflect.MethodInvoker;

import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;


public class HandlerWrapper {

	private MethodInvoker invoker;

	private Method method;

	private Class paramType;

	private Map<String, Integer> requestParam;

	public HandlerWrapper(Object target, Method method) {
		this.invoker = MethodInvoker.create(target, method);
		this.method = method;
		this.requestParam = initRequestParamMap(method);
		this.paramType = hasRequestParam() ? null : method.getParameterTypes()[0];
	}

	public Object invoke(Object... args) {
		return this.invoker.invoke(args);
	}

	public Object invokeRequestParam(Map<String, Object> params) {
		Object[] args = new Object[requestParam.size()];
		params.forEach((k, v) -> {
			args[requestParam.get(k)] = v;
		});
		return invoke(args);
	}

	public Method getMethod() {
		return method;
	}

	public Class getParamType() {
		return paramType;
	}

	private static Map<String, Integer> initRequestParamMap(Method method) {
		Map<String, Integer> map = new HashMap<>();
		Annotation[][] parameterAnnotations = method.getParameterAnnotations();
		for (int i = 0; i < parameterAnnotations.length; i++) {
			for (int j = 0; j < parameterAnnotations[0].length; j++) {
				Annotation annotation = parameterAnnotations[i][j];
				if (annotation instanceof RequestParam) {
					String paramName = ((RequestParam) annotation).value();
					if (map.containsKey(paramName)) {
						throw new RuntimeException("处理方法的参数列表中 RequestParam 注解的 value 值必须是唯一的");
					}
					map.put(paramName, i);
				}
			}
		}
		return map;
	}

	public boolean hasRequestParam() {
		return !requestParam.isEmpty();
	}

	@Override
	public String toString() {
		return "HandlerWrapper{" + "invoker=" + invoker + ", method=" + method + ", paramType=" + paramType + '}';
	}

}
